package impl

import (
	"context"
	"fmt"
	"gitee.com/kevin186/keyauth/apps/policy"
	"gitee.com/kevin186/keyauth/apps/role"
	"github.com/infraboard/mcube/exception"
)

func (s *service) ValidatePermission(ctx context.Context, req *policy.ValidatePermissionRequest) (*policy.Policy, error) {
	// 根据用户和命名空间找到该用户的授权策略
	// 由于使用了默认分页，只查询20条数据
	query := policy.NewQueryPolicyRequest()
	query.Namespace = req.Namespace
	query.Username = req.Username
	query.Page.PageSize = 100

	set, err := s.QueryPolicy(ctx, query)
	if err != nil {
		return nil, err
	}

	// 如果mongodb中没有创建policy，查出来的将是空值
	if len(set.Items) < 1 {
		return nil, fmt.Errorf("not find policySet in mongoDB")
	}

	// 获取用户的角色，从策略中抽取出来
	roleNames := set.Roles()

	s.log.Debugf("found roles: %s", roleNames)

	// 通过role模块查询所有role对象
	queryRoleReq := role.NewQueryRoleRequestWithName(roleNames)
	queryRoleReq.Page.PageSize = 100
	roles, err := s.role.QueryRole(ctx, queryRoleReq)
	if err != nil {
		return nil, err
	}

	// 根据查询该用户关联的角色
	hasPerm, ro := roles.HasPermission(role.NewPermissionRequest(req.Service, req.Resource, req.Action))
	if !hasPerm {
		return nil, exception.NewPermissionDeny("not permission access service %s, resource %s, action %s",
			req.Service,
			req.Resource,
			req.Action,
		)
	}

	p := set.GetPolicyByRole(ro.Spec.Name)

	// 判断查到的policy是否为空，如果为空直接返回，否则grpc报nil的错误
	if p == nil {
		return nil, fmt.Errorf("not found policy with role")
	}

	return p, nil
}

func (s *service) QueryPolicy(ctx context.Context, req *policy.QueryPolicyRequest) (*policy.PolicySet, error) {
	query := newQueryPolicyRequest(req)
	return s.query(ctx, query)
}

func (s *service) CreatePolicy(ctx context.Context, req *policy.CreatePolicyRequest) (*policy.Policy, error) {
	ins, err := policy.NewPolicy(req)
	if err != nil {
		return nil, exception.NewBadRequest("validate create book error, %s", err)
	}

	if err := s.save(ctx, ins); err != nil {
		return nil, err
	}
	return ins, nil
}
